package com.huawang.mdesign.model.service.util;

import com.huawang.business.constants.ErrorCode;
import com.huawang.business.dto.ProjectDTO;
import com.huawang.business.dto.project.ProjectConfig;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.util.ObjectMapperFactory;
import com.huawang.mdesign.model.service.dto.ProjectConfigDTO;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.model.FileHeader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * @author zhaoww
 */
@Slf4j
public class ReadMd3Utils {
    /**
     * 缓存config.json文件中读取出来的扩展包内容
     */
    public static final String MOF_FILES_MOF_PROJECT_DB = "mofFiles/mofModel/mofProject.db";
    private static final String MOF_PROJECT_FILE_NAME = "mofProject.json";
    private static final String CONFIG_FILE_NAME = "config.json";
    private static final String PROFILE_CONFIG = "mofFiles/mofModel/profileConfig.json";

    private ReadMd3Utils() {
    }

    public static class MD3FileInfo {
        /**
         * 缓存解压缩出来的文件 文件名和文件内容
         */
        private final Map<String, String> fileMap = new HashMap<>(16);

        public void putFile(String name, String content) {
            fileMap.put(name, content);
        }

        /**
         * 从config.json中读取项目中使用到的扩展包名称
         */
        public ProjectConfig readConfig() {
            try {
                String config = fileMap.get(CONFIG_FILE_NAME);
                return ObjectMapperFactory.getMapper().readValue(config, ProjectConfig.class);
            } catch (Exception e) {
                throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
            }
        }

        @Nullable
        public String readMofProject() {
            return fileMap.get(MOF_PROJECT_FILE_NAME);
        }

        @Nullable
        public String readProfileConfig() {
            return fileMap.get(PROFILE_CONFIG);
        }

    }

    /**
     * 解压md3或者md3p文件
     *
     * @param path
     * @return
     */
    @NotNull
    public static MD3FileInfo unZip(String path) {
        MD3FileInfo md3FileInfo = new MD3FileInfo();
        ZipEntry ze;
        try (ZipFile zipFile = new ZipFile(path);
             InputStream in = new BufferedInputStream(Files.newInputStream(Paths.get(path)));
             ZipInputStream zin = new ZipInputStream(in)) {
            while ((ze = zin.getNextEntry()) != null) {
                if (!ze.isDirectory() && !ze.getName().equals(MOF_FILES_MOF_PROJECT_DB)) {
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(zipFile.getInputStream(ze),
                                    StandardCharsets.UTF_8));
                    StringBuilder line = new StringBuilder();
                    while (br.ready()) {
                        line.append(br.readLine());
                    }
                    md3FileInfo.putFile(ze.getName(), line.toString());
                    br.close();
                }
            }
            zin.closeEntry();
        } catch (IOException e) {
            throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
        }

        return md3FileInfo;
    }

    /**
     * 读取md3或者md3p文件的mofProject
     *
     * @param path
     * @return
     */
    @NotNull
    public static ProjectDTO unZipToProject(String path) {
        try (final net.lingala.zip4j.ZipFile localFile = new net.lingala.zip4j.ZipFile(path)) {
            FileHeader header = localFile.getFileHeader(MOF_PROJECT_FILE_NAME);
            return ObjectMapperFactory.getMapper().readValue(localFile.getInputStream(header), ProjectDTO.class);
        } catch (Exception e) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_DATA_READ_ERROR, e);
        }

    }

    /**
     * 解压md3或者md3p文件
     *
     * @param path
     * @return
     */
    @NotNull
    public static ProjectConfigDTO unZipToConfig(String path) {
        try (final net.lingala.zip4j.ZipFile localFile = new net.lingala.zip4j.ZipFile(path)) {
            FileHeader header = localFile.getFileHeader(CONFIG_FILE_NAME);
            return ObjectMapperFactory.getMapper().readValue(localFile.getInputStream(header), ProjectConfigDTO.class);
        } catch (Exception e) {
            throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
        }
    }


}
